package cn.com.cym.gamezao.service.recruit.impl;

import cn.com.cym.gamezao.base.BaseImpl;
import cn.com.cym.gamezao.base.BaseRepository;
import cn.com.cym.gamezao.base.ResultResponse;
import cn.com.cym.gamezao.base.SearchPage;
import cn.com.cym.gamezao.entity.authorize.User;
import cn.com.cym.gamezao.entity.recruit.Job;
import cn.com.cym.gamezao.entity.xmu.recruit.ApplyLog;
import cn.com.cym.gamezao.entity.xmu.recruit.UserApply;
import cn.com.cym.gamezao.enums.ApplyStatus;
import cn.com.cym.gamezao.exception.BaseException;
import cn.com.cym.gamezao.jwt.RequestUser;
import cn.com.cym.gamezao.repository.recruit.JobRepository;
import cn.com.cym.gamezao.service.recruit.ApplyLogService;
import cn.com.cym.gamezao.service.recruit.JobService;
import cn.com.cym.gamezao.service.recruit.UserApplyService;
import cn.com.cym.gamezao.util.CommonUtils;
import cn.hutool.core.util.ReflectUtil;
import lombok.SneakyThrows;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.lang.reflect.Field;
import java.util.Map;

@Service
@Transactional(rollbackFor = Exception.class)
public class JobImpl extends BaseImpl<Job> implements JobService {

    final JobRepository thisRepository;

    final UserApplyService userApplyRepository;

    final ApplyLogService applyLogRepository;

    public JobImpl(JobRepository jobRepository,UserApplyService userApplyRepository,ApplyLogService applyLogRepository){
        this.thisRepository=jobRepository;
        this.userApplyRepository = userApplyRepository;
        this.applyLogRepository = applyLogRepository;
    }

    @Override
    public BaseRepository<Job, Long> getJpaRepository() {
        return this.thisRepository;
    }

    @Override
    public Page<Job> findByPageable(SearchPage searchPage) {
        String[] sortBy = searchPage.getSortBy().toArray(new String[searchPage.getSortBy().size()]);

        Pageable pageable = PageRequest.of(searchPage.getCurrent()-1, searchPage.getPageSize(), searchPage.getSort(), sortBy);

        Specification<Job> specification = new Specification<>() {

            private static final long serialVersionUID = -2661077778894635593L;

            /**
             * @param root: 代表查询的实体类.
             * @param query: 可以从中可到 Root 对象, 即告知 JPA Criteria 查询要查询哪一个实体类. 还可以
             * 来添加查询条件, 还可以结合 EntityManager 对象得到最终查询的 TypedQuery 对象.
             * @param  cb: CriteriaBuilder 对象. 用于创建 Criteria 相关对象的工厂. 当然可以从中获取到 Predicate 对象
             * @return  Predicate 类型, 代表一个查询条件.
             */
            @SneakyThrows
            @Override
            public Predicate toPredicate(Root<Job> root,
                                         CriteriaQuery<?> query, CriteriaBuilder cb) {
                final Map<String, Field> fieldMap = ReflectUtil.getFieldMap(Job.class);
                return cb.and(CommonUtils.pageSet(fieldMap,searchPage,cb,root));
            }
        };
        return this.thisRepository.findAll(specification, pageable);
    }


    @Override
    public void apply(Long id) {
        final User user = RequestUser.get();
        final Job job = thisRepository.getById(id);
        final UserApply byJobAndUser = this.userApplyRepository.findByJobAndUser(job, user);

        if(byJobAndUser!=null && !"驳回".equals(byJobAndUser.getApplyStatus().getValue())){
            throw new BaseException("已申请该岗位，请勿重复申请",new ResultResponse("已申请该岗位，请勿重复申请", HttpStatus.BAD_REQUEST.value()));
        }
        if("不通过".equals(byJobAndUser.getApplyStatus().getValue())){
            throw new BaseException("该岗位个人无法满足申请条件，无法申请",new ResultResponse("该岗位个人无法满足申请条件，无法申请", HttpStatus.BAD_REQUEST.value()));
        }

        UserApply userApply = new UserApply().setUser(user).setJob(job).setApplyStatus(ApplyStatus.APPLY);

        // 保存对象
        this.userApplyRepository.save(userApply);

        ApplyLog applyLog = new ApplyLog().setApplyStatus(ApplyStatus.APPLY).setUserApply(userApply).setUser(user);

        this.applyLogRepository.save(applyLog);
        // final UserApply userApply = this.userApplyRepository.findById(id).get();
        //排查是否重复申请
    }
}
